package net.mindview.atunit;

import static net.mindview.util.Print.print;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.util.HashMap;
import java.util.Map;

import net.mindview.util.BinaryFile;
import net.mindview.util.Directory;

public class ClassNameFinderMY {
	public static String thisClass(byte[] classBytes) {
		Map<Integer, Integer> offsetTable = new HashMap<Integer, Integer>();
		Map<Integer, String> classNameTable = new HashMap<Integer, String>();
		try {
			DataInputStream data = new DataInputStream(
					new ByteArrayInputStream(classBytes));
			int magic = data.readInt(); // 0xcafebabe
			int minorVersion = data.readShort();
			int majorVersion = data.readShort();
			int constant_pool_count = data.readShort();
			int[] constant_pool = new int[constant_pool_count];
			for (int i = 1; i < constant_pool_count; i++) {
				int tag = data.read();
				int tableSize;
				switch (tag) {
				case 1: // UTF
					int length = data.readShort();
					char[] bytes = new char[length];
					for (int k = 0; k < bytes.length; k++)
						bytes[k] = (char) data.read();
					String className = new String(bytes);
					classNameTable.put(i, className);
					break;
				case 5: // LONG
				case 6: // DOUBLE
					data.readLong(); // discard 8 bytes
					i++; // Special skip necessary
					break;
				case 7: // CLASS
					int offset = data.readShort();
					offsetTable.put(i, offset);
					break;
				case 8: // STRING
					data.readShort(); // discard 2 bytes
					break;
				case 3: // INTEGER
				case 4: // FLOAT
				case 9: // FIELD_REF
				case 10: // METHOD_REF
				case 11: // INTERFACE_METHOD_REF
				case 12: // NAME_AND_TYPE
					data.readInt(); // discard 4 bytes;
					break;
				default:
					throw new RuntimeException("Bad tag " + tag);
				}
			}
			short access_flags = data.readShort();
			int this_class = data.readShort();
			int super_class = data.readShort();
			return classNameTable.get(offsetTable.get(this_class)).replace('/',
					'.');
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	// Demonstration:
	public static void main(String[] args) throws Exception {
		if (args.length > 0) {
			for (String arg : args)
				print(thisClass(BinaryFile.read(new File(arg))));
		} else
			// Walk the entire tree:
			for (File klass : Directory.walk(".", ".*\\.class"))
				print(thisClass(BinaryFile.read(klass)));
	}
}
